/*
 * GameComponentManager.cpp
 *
 *  Created on: May 13, 2012
 *      Author: mklingen
 */

#include "GameComponentManager.h"
#include "GameWindow.h"

namespace kling
{

    GameComponentManager::GameComponentManager(GameWindow* gameWindow) :
           m_gameWindow(gameWindow), m_isInitialized(false)
    {
        m_maxGlobalID = (GlobalComponentID)(0);
        m_rootComponent = new GameComponent(this, "Root");
        AddComponent(m_rootComponent);
    }

    GameComponentManager::~GameComponentManager()
    {

    }

    void GameComponentManager::Initialize()
    {
        m_rootComponent->Initialize();
        m_isInitialized = true;
    }

    bool GameComponentManager::AddComponent(GameComponent* gameComponent, GlobalComponentID id)
    {
        if(HasComponentWithGlobalID(id))
        {
            return false;
        }
        else
        {
            if(id == INVALID_GLOBAL_ID)
            {
                id = GetNextGlobalID();
            }

            gameComponent->SetGlobalID(id);
            m_components[id] = gameComponent;
        }
    }

    void GameComponentManager::Update(double deltaTimeSeconds)
    {
        m_rootComponent->ComputeGlobalPoseRecursive();

        std::vector<GlobalComponentID> toDestroy;

        for(std::map<GlobalComponentID, GameComponent*>::iterator it = m_components.begin(); it != m_components.end(); it++)
        {
            if(it->second->IsDestroyed())
            {
                toDestroy.push_back(it->first);
            }
            else
            {
                it->second->Update(deltaTimeSeconds);
            }
        }

        for(size_t i = 0; i < toDestroy.size(); i++)
        {
            GameComponent* component = m_components[toDestroy[i]];
            delete component;
            m_components.erase(toDestroy[i]);
        }
    }

    void GameComponentManager::Render(double deltaTimeSeconds)
    {
        for(std::map<GlobalComponentID, GameComponent*>::iterator it = m_components.begin(); it != m_components.end(); it++)
        {
            it->second->Render(deltaTimeSeconds);
        }
    }

    GameComponent* GameComponentManager::GetComponentWithGlobalID(GlobalComponentID id)
    {
        if(HasComponentWithGlobalID(id))
        {
            return m_components[id];
        }
        else
        {
            return NULL;
        }
    }

    bool GameComponentManager::IsInitialized()
    {
        return m_isInitialized;
    }

    void GameComponentManager::InitializeAllComponents()
    {
        for(std::map<GlobalComponentID, GameComponent*>::iterator it = m_components.begin(); it != m_components.end(); it++)
        {
            if(!(it->second->IsInitialized()))
            {
                it->second->Initialize();
            }
        }
    }

    void GameComponentManager::HandleKeyEvent(QKeyEvent* keyEvent)
    {
        for(std::map<GlobalComponentID, GameComponent*>::iterator it = m_components.begin(); it != m_components.end(); it++)
        {
            it->second->HandleKeyEvent(keyEvent);
        }
    }

    void GameComponentManager::HandleMouseEvent(QMouseEvent* mouseEvent)
    {
        for(std::map<GlobalComponentID, GameComponent*>::iterator it = m_components.begin(); it != m_components.end(); it++)
        {
            it->second->HandleMouseEvent(mouseEvent);
        }
    }

} /* namespace kling */
